using System;
using System.Collections.Generic;

namespace Windy.Transformations
{
    public abstract class TransformSinkBase<TInput, TOutput, TClass> : ITransformSink<TInput, TOutput>, IDisposable
        where TClass : TransformSinkBase<TInput, TOutput, TClass>
    {
        #region Initializers

        #region Constructors

        protected TransformSinkBase()
        { }

        public TransformSinkBase(
            Action transformBeginHandler = null,
            Action transformCompleteHandler = null,
            Action transformAbortHandler = null)
        {
            Initialize(
                transformBeginHandler,
                transformCompleteHandler,
                transformAbortHandler);
        }

        #endregion

        protected virtual void Initialize(
            Action transformBeginHandler,
            Action transformCompleteHandler,
            Action transformAbortHandler)
        {
            IsInTransformation = false;

            TransformBeginHandler = transformBeginHandler;
            TransformCompleteHandler = transformCompleteHandler;
            TransformAborHandler = transformAbortHandler;
        }

        #endregion

        #region IRuleSetOutputHandler<TItem> Members

        public virtual bool IsInTransformation { get; protected set; }

        #region Tranform Data Sinks

        public abstract void OnVoidTransform(int index, TInput inputItem);
        public abstract void OnMonoTransform(int index, TInput inputItem, TOutput outputItem);
        public abstract void OnVaryTransform(int index, TInput inputItem, IEnumerable<TOutput> outputItems);

        #endregion

        #region Transform Workflow Handlers

        protected Action TransformBeginHandler;
        public virtual void OnTransformBegun()
        {
            if (IsInTransformation)
            {
                throw new InvalidOperationException("Transformation is in progress");
            }
            else
            {
                IsInTransformation = true;

                if (TransformBeginHandler != null)
                    TransformBeginHandler();
            }
        }
        public TClass SetupTransformBeginHandler(Action handler)
        {
            TransformBeginHandler = handler;
            return this as TClass;
        }

        protected Action TransformCompleteHandler;
        public virtual void OnTransformCompleted()
        {
            if (IsInTransformation)
            {
                if (TransformCompleteHandler != null)
                    TransformCompleteHandler();

                IsInTransformation = false;
            }
        }
        public TClass SetupTransformCompleteHandler(Action handler)
        {
            TransformCompleteHandler = handler;
            return this as TClass;
        }

        protected Action TransformAborHandler;
        public virtual void OnTransformAborted()
        {
            if (IsInTransformation)
            {
                if (TransformAborHandler != null)
                    TransformAborHandler();

                IsInTransformation = false;
            }
        }
        public TClass SetupTransformAborHandler(Action handler)
        {
            TransformAborHandler = handler;
            return this as TClass;
        }

        #endregion

        #endregion

        #region IDisposable Members

        public virtual void Dispose()
        {
            if (IsInTransformation)
                OnTransformCompleted();
        }

        #endregion
    }
}
